<template>
  <div class="training-monitoring">
    <div class="page-header">
      <h2>训练监控</h2>
      <div class="header-actions">
        <el-button type="primary" @click="startTraining">
          <el-icon><VideoPlay /></el-icon>
          开始训练
        </el-button>
        <el-button @click="refreshData">
          <el-icon><Refresh /></el-icon>
          刷新
        </el-button>
      </div>
    </div>

    <!-- 训练概览 -->
    <div class="training-overview">
      <div class="overview-card">
        <div class="card-icon training">
          <el-icon><Loading /></el-icon>
        </div>
        <div class="card-content">
          <div class="card-number">{{ overview.runningTasks }}</div>
          <div class="card-label">训练中</div>
        </div>
      </div>
      
      <div class="overview-card">
        <div class="card-icon waiting">
          <el-icon><Clock /></el-icon>
        </div>
        <div class="card-content">
          <div class="card-number">{{ overview.waitingTasks }}</div>
          <div class="card-label">等待中</div>
        </div>
      </div>
      
      <div class="overview-card">
        <div class="card-icon completed">
          <el-icon><Check /></el-icon>
        </div>
        <div class="card-content">
          <div class="card-number">{{ overview.completedTasks }}</div>
          <div class="card-label">已完成</div>
        </div>
      </div>
      
      <div class="overview-card">
        <div class="card-icon failed">
          <el-icon><Close /></el-icon>
        </div>
        <div class="card-content">
          <div class="card-number">{{ overview.failedTasks }}</div>
          <div class="card-label">失败</div>
        </div>
      </div>
    </div>

    <!-- 训练任务列表 -->
    <div class="training-tasks">
      <div class="task-header">
        <h3>训练任务</h3>
        <el-select v-model="statusFilter" placeholder="筛选状态" clearable>
          <el-option label="全部" value="" />
          <el-option label="训练中" value="running" />
          <el-option label="等待中" value="waiting" />
          <el-option label="已完成" value="completed" />
          <el-option label="失败" value="failed" />
        </el-select>
      </div>
      
      <div class="task-list">
        <div 
          v-for="task in filteredTasks" 
          :key="task.id"
          class="task-item"
          @click="selectTask(task)"
          :class="{ active: selectedTask?.id === task.id }"
        >
          <div class="task-info">
            <div class="task-name">{{ task.name }}</div>
            <div class="task-type">{{ task.type }}</div>
            <div class="task-time">{{ formatDate(task.startTime) }}</div>
          </div>
          
          <div class="task-status">
            <el-tag :type="getStatusColor(task.status)">
              {{ getStatusLabel(task.status) }}
            </el-tag>
          </div>
          
          <div class="task-progress">
            <el-progress 
              :percentage="task.progress" 
              :status="getProgressStatus(task.status)"
              :stroke-width="6"
            />
          </div>
        </div>
      </div>
    </div>

    <!-- 训练详情 -->
    <div class="training-details" v-if="selectedTask">
      <div class="detail-header">
        <h3>{{ selectedTask.name }}</h3>
        <div class="detail-actions">
          <el-button 
            v-if="selectedTask.status === 'running'"
            type="warning" 
            size="small"
            @click="pauseTraining(selectedTask)"
          >
            <el-icon><VideoPause /></el-icon>
            暂停
          </el-button>
          <el-button 
            v-if="selectedTask.status === 'running'"
            type="danger" 
            size="small"
            @click="stopTraining(selectedTask)"
          >
            <el-icon><VideoPlay /></el-icon>
            停止
          </el-button>
          <el-button size="small" @click="viewLogs(selectedTask)">
            <el-icon><Document /></el-icon>
            查看日志
          </el-button>
        </div>
      </div>

      <div class="detail-content">
        <div class="detail-metrics">
          <div class="metric-item">
            <div class="metric-label">当前轮次</div>
            <div class="metric-value">{{ selectedTask.currentEpoch }}/{{ selectedTask.totalEpochs }}</div>
          </div>
          <div class="metric-item">
            <div class="metric-label">训练损失</div>
            <div class="metric-value">{{ selectedTask.trainLoss }}</div>
          </div>
          <div class="metric-item">
            <div class="metric-label">验证损失</div>
            <div class="metric-value">{{ selectedTask.validLoss }}</div>
          </div>
          <div class="metric-item">
            <div class="metric-label">准确率</div>
            <div class="metric-value">{{ selectedTask.accuracy }}%</div>
          </div>
        </div>

        <div class="detail-chart">
          <div class="chart-container">
            <div ref="trainingChart" class="chart"></div>
          </div>
        </div>

        <div class="detail-config">
          <h4>训练配置</h4>
          <div class="config-grid">
            <div class="config-item">
              <span class="config-label">学习率:</span>
              <span class="config-value">{{ selectedTask.config.learningRate }}</span>
            </div>
            <div class="config-item">
              <span class="config-label">批次大小:</span>
              <span class="config-value">{{ selectedTask.config.batchSize }}</span>
            </div>
            <div class="config-item">
              <span class="config-label">优化器:</span>
              <span class="config-value">{{ selectedTask.config.optimizer }}</span>
            </div>
            <div class="config-item">
              <span class="config-label">数据集:</span>
              <span class="config-value">{{ selectedTask.config.dataset }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 日志查看对话框 -->
    <el-dialog v-model="logDialogVisible" title="训练日志" width="80%">
      <div class="log-container">
        <div class="log-header">
          <el-button size="small" @click="refreshLogs">
            <el-icon><Refresh /></el-icon>
            刷新
          </el-button>
          <el-button size="small" @click="clearLogs">
            <el-icon><Delete /></el-icon>
            清空
          </el-button>
        </div>
        <div class="log-content">
          <pre>{{ logContent }}</pre>
        </div>
      </div>
    </el-dialog>

    <!-- 开始训练对话框 -->
    <el-dialog v-model="trainingDialogVisible" title="开始训练" width="600px">
      <el-form :model="trainingForm" :rules="trainingRules" ref="trainingFormRef" label-width="120px">
        <el-form-item label="模型名称" prop="name">
          <el-input v-model="trainingForm.name" placeholder="请输入模型名称" />
        </el-form-item>
        <el-form-item label="模型类型" prop="type">
          <el-select v-model="trainingForm.type" placeholder="请选择模型类型">
            <el-option label="文本检测 (XLNet/BERT)" value="text-detection" />
            <el-option label="图像识别 (ResNet50/EfficientNet)" value="image-recognition" />
            <el-option label="视频分析 (CNN+LSTM)" value="video-analysis" />
            <el-option label="音频检测 (深度神经网络)" value="audio-detection" />
            <el-option label="多模态融合" value="multimodal-fusion" />
          </el-select>
        </el-form-item>
        <el-form-item label="数据集" prop="dataset">
          <el-select v-model="trainingForm.dataset" placeholder="请选择数据集">
            <el-option label="中文谣言检测数据集" value="chinese-rumor-dataset" />
            <el-option label="图像篡改检测数据集" value="image-tampering-dataset" />
            <el-option label="Deepfake视频数据集" value="deepfake-video-dataset" />
            <el-option label="声纹识别数据集" value="voiceprint-dataset" />
            <el-option label="AI生成内容数据集" value="ai-generated-content-dataset" />
            <el-option label="诈骗短信数据集" value="fraud-sms-dataset" />
            <el-option label="多模态融合数据集" value="multimodal-fusion-dataset" />
          </el-select>
        </el-form-item>
        <el-form-item label="训练轮次" prop="epochs">
          <el-input-number v-model="trainingForm.epochs" :min="1" :max="1000" />
        </el-form-item>
        <el-form-item label="学习率" prop="learningRate">
          <el-input-number v-model="trainingForm.learningRate" :min="0.0001" :max="1" :step="0.0001" />
        </el-form-item>
        <el-form-item label="批次大小" prop="batchSize">
          <el-input-number v-model="trainingForm.batchSize" :min="1" :max="512" />
        </el-form-item>
      </el-form>
      
      <template #footer>
        <div class="dialog-footer">
          <el-button @click="trainingDialogVisible = false">取消</el-button>
          <el-button type="primary" @click="submitTraining" :loading="submitting">
            开始训练
          </el-button>
        </div>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, computed, onMounted, onUnmounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import * as echarts from 'echarts'
import { 
  VideoPlay, VideoPause, Refresh, Loading, Clock, Check, Close, 
  Document, Delete 
} from '@element-plus/icons-vue'

// 数据状态
const submitting = ref(false)
const logDialogVisible = ref(false)
const trainingDialogVisible = ref(false)
const statusFilter = ref('')
const selectedTask = ref(null)
const trainingFormRef = ref(null)

// 图表相关
const trainingChart = ref(null)
let trainingChartInstance = null

// 训练概览
const overview = reactive({
  runningTasks: 3,
  waitingTasks: 1,
  completedTasks: 2,
  failedTasks: 1
})

// 训练表单
const trainingForm = reactive({
  name: '',
  type: '',
  dataset: '',
  epochs: 100,
  learningRate: 0.001,
  batchSize: 32
})

// 表单验证规则
const trainingRules = {
  name: [
    { required: true, message: '请输入模型名称', trigger: 'blur' }
  ],
  type: [
    { required: true, message: '请选择模型类型', trigger: 'change' }
  ],
  dataset: [
    { required: true, message: '请选择数据集', trigger: 'change' }
  ]
}

// 训练任务列表
const trainingTasks = ref([
  {
    id: 1,
    name: 'XLNet-Base-Chinese-Rumor-v2.3',
    type: 'text-detection',
    status: 'running',
    progress: 65,
    startTime: '2024-01-15T10:30:00',
    currentEpoch: 65,
    totalEpochs: 100,
    trainLoss: 0.234,
    validLoss: 0.298,
    accuracy: 94.2,
    config: {
      learningRate: 0.001,
      batchSize: 32,
      optimizer: 'AdamW',
      dataset: 'chinese-rumor-dataset'
    }
  },
  {
    id: 2,
    name: 'ResNet50-ImageTampering-v3.1',
    type: 'image-recognition',
    status: 'running',
    progress: 42,
    startTime: '2024-01-15T09:15:00',
    currentEpoch: 84,
    totalEpochs: 200,
    trainLoss: 0.421,
    validLoss: 0.456,
    accuracy: 91.8,
    config: {
      learningRate: 0.0001,
      batchSize: 16,
      optimizer: 'SGD',
      dataset: 'image-tampering-dataset'
    }
  },
  {
    id: 3,
    name: 'EfficientNet-B4-AIGenerated-v1.8',
    type: 'image-recognition',
    status: 'waiting',
    progress: 0,
    startTime: '2024-01-15T16:00:00',
    currentEpoch: 0,
    totalEpochs: 150,
    trainLoss: 0,
    validLoss: 0,
    accuracy: 0,
    config: {
      learningRate: 0.0005,
      batchSize: 24,
      optimizer: 'AdamW',
      dataset: 'ai-generated-content-dataset'
    }
  },
  {
    id: 4,
    name: 'CNN-LSTM-DeepfakeVideo-v2.0',
    type: 'video-analysis',
    status: 'completed',
    progress: 100,
    startTime: '2024-01-14T14:00:00',
    currentEpoch: 120,
    totalEpochs: 120,
    trainLoss: 0.156,
    validLoss: 0.189,
    accuracy: 93.7,
    config: {
      learningRate: 0.0002,
      batchSize: 8,
      optimizer: 'Adam',
      dataset: 'deepfake-video-dataset'
    }
  },
  {
    id: 5,
    name: 'DeepSpeech-VoiceprintAuth-v1.5',
    type: 'audio-detection',
    status: 'completed',
    progress: 100,
    startTime: '2024-01-13T11:30:00',
    currentEpoch: 80,
    totalEpochs: 80,
    trainLoss: 0.089,
    validLoss: 0.112,
    accuracy: 96.4,
    config: {
      learningRate: 0.0003,
      batchSize: 64,
      optimizer: 'RMSprop',
      dataset: 'voiceprint-dataset'
    }
  },
  {
    id: 6,
    name: 'BERT-FraudSMS-Detection-v1.2',
    type: 'text-detection',
    status: 'failed',
    progress: 23,
    startTime: '2024-01-15T08:00:00',
    currentEpoch: 23,
    totalEpochs: 100,
    trainLoss: 0.678,
    validLoss: 0.745,
    accuracy: 76.3,
    config: {
      learningRate: 0.002,
      batchSize: 48,
      optimizer: 'Adam',
      dataset: 'fraud-sms-dataset'
    }
  },
  {
    id: 7,
    name: 'MultiModal-Fusion-v1.0',
    type: 'multimodal-fusion',
    status: 'running',
    progress: 18,
    startTime: '2024-01-15T12:00:00',
    currentEpoch: 27,
    totalEpochs: 150,
    trainLoss: 0.523,
    validLoss: 0.567,
    accuracy: 87.2,
    config: {
      learningRate: 0.0001,
      batchSize: 12,
      optimizer: 'AdamW',
      dataset: 'multimodal-fusion-dataset'
    }
  }
])

// 日志内容
const logContent = ref(`[2024-01-15 10:30:00] Starting XLNet-Base-Chinese-Rumor-v2.3 training...
[2024-01-15 10:30:01] Loading Chinese rumor detection dataset...
[2024-01-15 10:30:05] Dataset loaded: 150,000 samples (120,000 train, 30,000 val)
[2024-01-15 10:30:05] Initializing XLNet model with 110M parameters
[2024-01-15 10:30:06] Model architecture: XLNet-Base-Chinese
[2024-01-15 10:30:06] Optimizer: AdamW, Learning Rate: 0.001, Batch Size: 32
[2024-01-15 10:30:06] Starting training for 100 epochs...
[2024-01-15 10:31:02] Epoch 1/100 - Train Loss: 0.845, Val Loss: 0.892, Accuracy: 72.3%
[2024-01-15 10:32:01] Epoch 2/100 - Train Loss: 0.623, Val Loss: 0.687, Accuracy: 78.9%
[2024-01-15 10:33:00] Epoch 3/100 - Train Loss: 0.498, Val Loss: 0.543, Accuracy: 82.4%
[2024-01-15 10:34:15] Epoch 5/100 - Train Loss: 0.412, Val Loss: 0.456, Accuracy: 85.7%
[2024-01-15 10:35:30] Epoch 10/100 - Train Loss: 0.345, Val Loss: 0.398, Accuracy: 88.2%
[2024-01-15 10:38:45] Epoch 20/100 - Train Loss: 0.287, Val Loss: 0.342, Accuracy: 91.1%
[2024-01-15 10:42:12] Epoch 30/100 - Train Loss: 0.256, Val Loss: 0.318, Accuracy: 92.6%
[2024-01-15 10:45:23] Epoch 50/100 - Train Loss: 0.245, Val Loss: 0.305, Accuracy: 93.8%
[2024-01-15 11:15:34] Epoch 65/100 - Train Loss: 0.234, Val Loss: 0.298, Accuracy: 94.2%
[2024-01-15 11:15:34] Validation metrics: Precision: 0.943, Recall: 0.941, F1-Score: 0.942
[2024-01-15 11:15:34] Best model saved at epoch 65
[2024-01-15 11:15:34] Training continuing...`)

// 计算属性
const filteredTasks = computed(() => {
  if (!statusFilter.value) return trainingTasks.value
  return trainingTasks.value.filter(task => task.status === statusFilter.value)
})

// 方法
const selectTask = (task) => {
  selectedTask.value = task
  setTimeout(() => {
    initTrainingChart()
  }, 100)
}

const refreshData = () => {
  ElMessage.success('数据刷新成功')
}

const startTraining = () => {
  trainingDialogVisible.value = true
}

const submitTraining = async () => {
  if (!trainingFormRef.value) return
  
  try {
    await trainingFormRef.value.validate()
    submitting.value = true
    
    await new Promise(resolve => setTimeout(resolve, 2000))
    
    const newTask = {
      id: Date.now(),
      name: trainingForm.name,
      type: trainingForm.type,
      status: 'waiting',
      progress: 0,
      startTime: new Date().toISOString(),
      currentEpoch: 0,
      totalEpochs: trainingForm.epochs,
      trainLoss: 0,
      validLoss: 0,
      accuracy: 0,
      config: {
        learningRate: trainingForm.learningRate,
        batchSize: trainingForm.batchSize,
        optimizer: 'Adam',
        dataset: trainingForm.dataset
      }
    }
    
    trainingTasks.value.unshift(newTask)
    overview.waitingTasks++
    
    ElMessage.success('训练任务创建成功')
    trainingDialogVisible.value = false
    resetTrainingForm()
  } catch (error) {
    console.error('创建训练任务失败:', error)
  } finally {
    submitting.value = false
  }
}

const resetTrainingForm = () => {
  Object.assign(trainingForm, {
    name: '',
    type: '',
    dataset: '',
    epochs: 100,
    learningRate: 0.001,
    batchSize: 32
  })
}

const pauseTraining = async (task) => {
  try {
    await ElMessageBox.confirm('确定要暂停此训练任务吗？', '确认操作', {
      type: 'warning'
    })
    
    task.status = 'paused'
    ElMessage.success('训练任务已暂停')
  } catch (error) {
    // 用户取消操作
  }
}

const stopTraining = async (task) => {
  try {
    await ElMessageBox.confirm('确定要停止此训练任务吗？停止后无法恢复！', '确认操作', {
      type: 'warning'
    })
    
    task.status = 'stopped'
    ElMessage.success('训练任务已停止')
  } catch (error) {
    // 用户取消操作
  }
}

const viewLogs = (task) => {
  selectedTask.value = task
  logDialogVisible.value = true
}

const refreshLogs = () => {
  ElMessage.success('日志已刷新')
}

const clearLogs = () => {
  logContent.value = ''
  ElMessage.success('日志已清空')
}

const initTrainingChart = () => {
  if (!trainingChart.value) return
  
  trainingChartInstance = echarts.init(trainingChart.value)
  
  const option = {
    title: {
      text: '训练进度'
    },
    tooltip: {
      trigger: 'axis'
    },
    legend: {
      data: ['训练损失', '验证损失', '准确率']
    },
    xAxis: {
      type: 'category',
      data: Array.from({length: selectedTask.value.currentEpoch}, (_, i) => `Epoch ${i + 1}`)
    },
    yAxis: [
      {
        type: 'value',
        name: '损失',
        position: 'left'
      },
      {
        type: 'value',
        name: '准确率 (%)',
        position: 'right'
      }
    ],
    series: [
      {
        name: '训练损失',
        type: 'line',
        data: generateTrainingData(selectedTask.value.currentEpoch, 0.8, 0.2),
        smooth: true,
        itemStyle: { color: '#ff4757' }
      },
      {
        name: '验证损失',
        type: 'line',
        data: generateTrainingData(selectedTask.value.currentEpoch, 0.9, 0.25),
        smooth: true,
        itemStyle: { color: '#ffa502' }
      },
      {
        name: '准确率',
        type: 'line',
        yAxisIndex: 1,
        data: generateAccuracyData(selectedTask.value.currentEpoch, 60, 94),
        smooth: true,
        itemStyle: { color: '#2ed573' }
      }
    ]
  }
  
  trainingChartInstance.setOption(option)
}

const generateTrainingData = (epochs, start, end) => {
  const data = []
  for (let i = 0; i < epochs; i++) {
    const progress = i / epochs
    const value = start - (start - end) * progress + (Math.random() - 0.5) * 0.1
    data.push(Math.max(0, value).toFixed(3))
  }
  return data
}

const generateAccuracyData = (epochs, start, end) => {
  const data = []
  for (let i = 0; i < epochs; i++) {
    const progress = i / epochs
    const value = start + (end - start) * progress + (Math.random() - 0.5) * 5
    data.push(Math.min(100, Math.max(0, value)).toFixed(1))
  }
  return data
}

// 辅助函数
const getStatusLabel = (status) => {
  const labels = {
    running: '训练中',
    waiting: '等待中',
    completed: '已完成',
    failed: '失败',
    paused: '已暂停',
    stopped: '已停止'
  }
  return labels[status] || status
}

const getStatusColor = (status) => {
  const colors = {
    running: 'warning',
    waiting: 'info',
    completed: 'success',
    failed: 'danger',
    paused: 'warning',
    stopped: 'danger'
  }
  return colors[status] || 'info'
}

const getProgressStatus = (status) => {
  const statusMap = {
    running: undefined,
    waiting: undefined,
    completed: 'success',
    failed: 'exception',
    paused: 'warning',
    stopped: 'exception'
  }
  return statusMap[status]
}

const formatDate = (date) => {
  return new Date(date).toLocaleString('zh-CN')
}

// 生命周期
onMounted(() => {
  // 选择第一个任务
  if (trainingTasks.value.length > 0) {
    selectTask(trainingTasks.value[0])
  }
})

onUnmounted(() => {
  if (trainingChartInstance) {
    trainingChartInstance.dispose()
  }
})
</script>

<style scoped>
.training-monitoring {
  padding: 20px;
  background-color: #f5f5f5;
  min-height: 100vh;
}

.page-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 20px;
  padding: 20px;
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}

.page-header h2 {
  margin: 0;
  color: #333;
}

.header-actions {
  display: flex;
  gap: 10px;
}

.training-overview {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 20px;
  margin-bottom: 20px;
}

.overview-card {
  background: white;
  padding: 20px;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  display: flex;
  align-items: center;
  gap: 15px;
}

.card-icon {
  width: 50px;
  height: 50px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
  font-size: 20px;
}

.card-icon.training {
  background: #f093fb;
  animation: spin 2s linear infinite;
}

.card-icon.waiting {
  background: #74b9ff;
}

.card-icon.completed {
  background: #00b894;
}

.card-icon.failed {
  background: #e74c3c;
}

@keyframes spin {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

.card-content {
  flex: 1;
}

.card-number {
  font-size: 24px;
  font-weight: bold;
  color: #333;
  margin-bottom: 5px;
}

.card-label {
  color: #666;
  font-size: 14px;
}

.training-tasks {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  margin-bottom: 20px;
}

.task-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  border-bottom: 1px solid #e6e6e6;
}

.task-header h3 {
  margin: 0;
  color: #333;
}

.task-list {
  max-height: 400px;
  overflow-y: auto;
}

.task-item {
  display: flex;
  align-items: center;
  gap: 20px;
  padding: 15px 20px;
  border-bottom: 1px solid #f0f0f0;
  cursor: pointer;
  transition: background-color 0.2s;
}

.task-item:hover {
  background-color: #f8f9fa;
}

.task-item.active {
  background-color: #e6f7ff;
  border-left: 4px solid #1890ff;
}

.task-info {
  flex: 1;
}

.task-name {
  font-weight: bold;
  color: #333;
  margin-bottom: 5px;
}

.task-type {
  color: #666;
  font-size: 12px;
  margin-bottom: 5px;
}

.task-time {
  color: #999;
  font-size: 12px;
}

.task-status {
  width: 100px;
}

.task-progress {
  width: 150px;
}

.training-details {
  background: white;
  border-radius: 8px;
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  margin-bottom: 20px;
}

.detail-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 20px;
  border-bottom: 1px solid #e6e6e6;
}

.detail-header h3 {
  margin: 0;
  color: #333;
}

.detail-actions {
  display: flex;
  gap: 10px;
}

.detail-content {
  padding: 20px;
}

.detail-metrics {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(150px, 1fr));
  gap: 20px;
  margin-bottom: 20px;
}

.metric-item {
  text-align: center;
  padding: 15px;
  background: #f8f9fa;
  border-radius: 8px;
}

.metric-label {
  color: #666;
  font-size: 14px;
  margin-bottom: 5px;
}

.metric-value {
  font-size: 20px;
  font-weight: bold;
  color: #333;
}

.detail-chart {
  margin-bottom: 20px;
}

.chart-container {
  height: 300px;
  border: 1px solid #e6e6e6;
  border-radius: 8px;
}

.chart {
  width: 100%;
  height: 100%;
}

.detail-config h4 {
  margin: 0 0 15px 0;
  color: #333;
}

.config-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
  gap: 15px;
}

.config-item {
  display: flex;
  justify-content: space-between;
  padding: 10px;
  background: #f8f9fa;
  border-radius: 4px;
}

.config-label {
  color: #666;
  font-weight: bold;
}

.config-value {
  color: #333;
}

.log-container {
  height: 500px;
  display: flex;
  flex-direction: column;
}

.log-header {
  display: flex;
  gap: 10px;
  margin-bottom: 10px;
}

.log-content {
  flex: 1;
  background: #1e1e1e;
  color: #fff;
  padding: 15px;
  border-radius: 4px;
  overflow-y: auto;
  font-family: 'Courier New', monospace;
  font-size: 12px;
  line-height: 1.4;
}

.log-content pre {
  margin: 0;
  white-space: pre-wrap;
  word-wrap: break-word;
}

.dialog-footer {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
}

@media (max-width: 768px) {
  .training-monitoring {
    padding: 10px;
  }
  
  .training-overview {
    grid-template-columns: 1fr;
  }
  
  .detail-metrics {
    grid-template-columns: 1fr;
  }
  
  .config-grid {
    grid-template-columns: 1fr;
  }
  
  .page-header {
    flex-direction: column;
    gap: 15px;
  }
  
  .header-actions {
    width: 100%;
    justify-content: center;
  }
  
  .task-item {
    flex-direction: column;
    align-items: flex-start;
    gap: 10px;
  }
  
  .task-status,
  .task-progress {
    width: 100%;
  }
}
</style> 